Numerous bug fixes, and a slightly less perverted /proc interface.
XI_BUILD = xi_build
XI_PHYS_GRANT = xi_phys_grant
XI_PHYS_REVOKE = xi_phys_revoke
+XI_PHYS_PROBE = xi_phys_probe
all: $(XI_CREATE).o $(XI_START).o $(XI_STOP).o $(XI_DESTROY).o $(XI_BUILD).o \
- $(XI_PHYS_GRANT).o $(XI_PHYS_REVOKE).o
+ $(XI_PHYS_GRANT).o $(XI_PHYS_REVOKE).o $(XI_PHYS_PROBE).o
$(CC) -o $(XI_CREATE) $(XI_CREATE).o
$(CC) -o $(XI_BUILD) $(XI_BUILD).o
$(CC) -o $(XI_START) $(XI_START).o
$(CC) -o $(XI_DESTROY) $(XI_DESTROY).o
$(CC) -o $(XI_PHYS_GRANT) $(XI_PHYS_GRANT).o
$(CC) -o $(XI_PHYS_REVOKE) $(XI_PHYS_REVOKE).o
+ $(CC) -o $(XI_PHYS_PROBE) $(XI_PHYS_PROBE).o
$(XI_CREATE).o: $(XI_CREATE).c dom0_defs.h dom0_ops.h hypervisor_defs.h mem_defs.h
$(CC) -c $(XI_CREATE).c
$(XI_PHYS_REVOKE).o: $(XI_PHYS_REVOKE).c physdev.h
$(CC) -c $(XI_PHYS_REVOKE).c
+$(XI_PHYS_PROBE).o: $(XI_PHYS_PROBE).c physdev.h
+ $(CC) -c $(XI_PHYS_PROBE).c
+
install: all
- cp -a xi_list xi_vifinit xi_helper $(XI_CREATE) $(XI_BUILD) $(XI_START) $(XI_STOP) $(XI_DESTROY) $(XI_PHYSDEV_GRANT) $(XI_PHYS_REVOKE) ../../../install/bin
+ cp -a xi_list xi_vifinit xi_helper $(XI_CREATE) $(XI_BUILD) $(XI_START) $(XI_STOP) $(XI_DESTROY) $(XI_PHYSDEV_GRANT) $(XI_PHYS_REVOKE) $(XI_PHYS_PROBE).o../../../install/bin
chmod 755 ../../../install/bin/xi_list
chmod 755 ../../../install/bin/xi_vifinit
chmod 755 ../../../install/bin/xi_helper
#define XEN_BLOCK_PHYSDEV_GRANT 10 /* grant access to range of disk blocks */
-#define XEN_BLOCK_PHYSDEV_REVOKE 11 /* revoke access to range of disk blocks */
-#define XEN_BLOCK_PHYSDEV_PROBE 12 /* probe for a domain's physdev
+#define XEN_BLOCK_PHYSDEV_PROBE 11 /* probe for a domain's physdev
accesses */
+#define PHYSDISK_MODE_R 1
+#define PHYSDISK_MODE_W 2
typedef struct xp_disk
{
- int mode;
+ int mode; /* PHYSDISK_MODEs or 0 for revoke. */
int domain;
unsigned short device;
unsigned long start_sect;
{
xp_disk_t buf;
int fd;
+ char *strbuf;
if (argc != 6) {
fprintf(stderr, "Usage: xi_physdev_grant <r/rw> <domain> <device> <start sector> <n_sectors>\n");
else if (argv[1][1] == 'w')
buf.mode |= 2;
- buf.domain = atol(argv[2]);
buf.device = atol(argv[3]);
buf.start_sect = atol(argv[4]);
buf.n_sectors = atol(argv[5]);
- fd = open("/proc/xeno/dom0/phd", O_WRONLY);
+ asprintf(&strbuf, "/proc/xeno/dom%s/phd", argv[2]);
+ fd = open(strbuf, O_WRONLY);
if (fd < 0) {
- fprintf(stderr, "Can\'t open /proc/xeno/dom0/phd: %s.\n", strerror(errno));
+ fprintf(stderr, "Can\'t open %s: %s.\n", strbuf, strerror(errno));
return 1;
}
+ free(strbuf);
write(fd, &buf, sizeof(buf));
close(fd);
physdisk_probebuf_t buf;
int fd;
int x;
+ char *strbuf;
if (argc != 2) {
fprintf(stderr, "Usage: xi_phys_probe <domain_nr>\n");
return 1;
}
- fd = open("/proc/xeno/dom0/phd", O_RDONLY);
+ asprintf(&strbuf, "/proc/xeno/dom%s/phd", argv[1]);
+ fd = open(strbuf, O_RDONLY);
if (fd < 0) {
- fprintf(stderr, "Can\'t open /proc/xeno/dom0/phd: %s.\n",
- strerror(errno));
+ fprintf(stderr, "Can\'t open %s: %s.\n", strbuf, strerror(errno));
return 1;
}
+ free(strbuf);
memset(&buf, 0, sizeof(buf));
buf.n_aces = PHYSDISK_MAX_ACES_PER_REQUEST;
- while (buf.n_aces == PHYSDISK_MAX_ACES_PER_REQUEST ||
- buf.n_aces == 0) {
+ do {
buf.n_aces = PHYSDISK_MAX_ACES_PER_REQUEST;
- buf.domain = atol(argv[1]);
read(fd, &buf, sizeof(buf));
if (!buf.n_aces)
break;
- printf("Found %d ACEs\n", buf.n_aces);
-
for (x = 0; x < buf.n_aces; x++) {
printf("%x:[%x,%x) : %x\n", buf.entries[x].device,
buf.entries[x].start_sect,
buf.entries[x].mode);
}
buf.start_ind += buf.n_aces;
- }
+ } while (buf.n_aces == PHYSDISK_MAX_ACES_PER_REQUEST);
return 0;
}
{
xp_disk_t buf;
int fd;
+ char *strbuf;
if (argc != 5) {
fprintf(stderr, "Usage: xi_physdev_revoke <domain> <device> <start sector> <n_sectors>\n");
return 1;
}
- buf.domain = atol(argv[1]);
buf.device = atol(argv[2]);
+ buf.mode = 0;
buf.start_sect = atol(argv[3]);
buf.n_sectors = atol(argv[4]);
- fd = open("/proc/xeno/dom0/phd", O_WRONLY);
+ asprintf(&strbuf, "/proc/xeno/dom%s/phd", argv[1]);
+ fd = open(strbuf, O_WRONLY);
if (fd < 0) {
- fprintf(stderr, "Can\'t open /proc/xeno/dom0/phd: %s.\n", strerror(errno));
+ fprintf(stderr, "Can\'t open %s: %s.\n", strbuf, strerror(errno));
return 1;
}
+ free(strbuf);
write(fd, &buf, sizeof(buf));
close(fd);
static void dispatch_create_segment(struct task_struct *p, int index);
static void dispatch_delete_segment(struct task_struct *p, int index);
static void dispatch_grant_physdev(struct task_struct *p, int index);
-static void dispatch_revoke_physdev(struct task_struct *p, int index);
static void dispatch_probe_physdev(struct task_struct *p, int index);
static void make_response(struct task_struct *p, unsigned long id,
unsigned short op, unsigned long st);
dispatch_grant_physdev(p, i);
break;
- case XEN_BLOCK_PHYSDEV_REVOKE:
- dispatch_revoke_physdev(p, i);
- break;
-
case XEN_BLOCK_PHYSDEV_PROBE:
dispatch_probe_physdev(p, i);
break;
XEN_BLOCK_PHYSDEV_GRANT, result);
}
-static void dispatch_revoke_physdev(struct task_struct *p, int index)
-{
- blk_ring_t *blk_ring = p->blk_ring_base;
- unsigned long flags, buffer;
- xp_disk_t *xpd;
- int result;
-
- if ( p->domain != 0 )
- {
- DPRINTK("dispatch_grant_physdev called by dom%d\n", p->domain);
- result = 1;
- goto out;
- }
-
- buffer = blk_ring->ring[index].req.buffer_and_sects[0] & ~0x1FF;
-
- spin_lock_irqsave(&p->page_lock, flags);
- if ( !__buffer_is_valid(p, buffer, sizeof(xv_disk_t), 1) )
- {
- DPRINTK("Bad buffer in dispatch_grant_physdev\n");
- spin_unlock_irqrestore(&p->page_lock, flags);
- result = 1;
- goto out;
- }
- __lock_buffer(buffer, sizeof(xv_disk_t), 1);
- spin_unlock_irqrestore(&p->page_lock, flags);
-
- xpd = phys_to_virt(buffer);
- result = xen_physdisk_revoke(xpd);
-
- unlock_buffer(p, buffer, sizeof(xp_disk_t), 1);
-
- out:
- make_response(p, blk_ring->ring[index].req.id,
- XEN_BLOCK_PHYSDEV_REVOKE, result);
-}
-
static void dispatch_create_segment(struct task_struct *p, int index)
{
blk_ring_t *blk_ring = p->blk_ring_base;
#define MAX(a,b) ((a) > (b) ? (a) : (b))
-#if 0
+#if 1
#define DPRINTK printk
#else
#define DPRINTK(...)
unsigned short device;
unsigned long start_sect;
unsigned long n_sectors;
-#define PHYSDISK_MODE_R 1
-#define PHYSDISK_MODE_W 2
int mode;
};
cur_ace = list_entry(cur_ace_head, struct physdisk_ace,
list);
ace_end = cur_ace->start_sect + cur_ace->n_sectors;
- if (cur_ace->start_sect > kill_zone_end ||
- ace_end < start_sect)
+ if (cur_ace->start_sect >= kill_zone_end ||
+ ace_end <= start_sect)
continue;
+ DPRINTK("Killing ace [%x, %x) against kill zone [%x, %x)\n",
+ cur_ace->start_sect, ace_end, start_sect, kill_zone_end);
+
if (cur_ace->start_sect >= start_sect &&
- ace_end < kill_zone_end) {
+ ace_end <= kill_zone_end) {
/* ace entirely within kill zone -> kill it */
list_del(cur_ace_head);
- cur_ace_head = cur_ace_head->next;
+ cur_ace_head = cur_ace_head->prev;
kfree(cur_ace);
- } else if (ace_end < kill_zone_end) {
+ } else if (ace_end <= kill_zone_end) {
/* ace start before kill start, ace end in kill zone,
move ace end. */
cur_ace->n_sectors = start_sect - cur_ace->start_sect;
cur_ace->start_sect = kill_zone_end;
cur_ace->n_sectors = ace_end - cur_ace->start_sect;
} else {
- /* The fun one: the kill zone entirely includes the ace. */
+ /* The fun one: the ace entirely includes the kill zone. */
/* Cut the current ace down to just the bit before the kzone,
- create a new ace for the bit just after it. */
+ create a new ace for the bit just after it. */
new_ace = kmalloc(sizeof(*cur_ace), GFP_KERNEL);
new_ace->device = dev;
new_ace->start_sect = kill_zone_end;
cur_ace->n_sectors = start_sect - cur_ace->start_sect;
list_add(&new_ace->list, cur_ace_head);
- cur_ace_head = new_ace->list.next;
}
}
}
and we try to grant write access, or vice versa. */
xen_physdisk_revoke_access(dev, start_sect, n_sectors, p);
- cur_ace = kmalloc(sizeof(*cur_ace), GFP_KERNEL);
- cur_ace->device = dev;
- cur_ace->start_sect = start_sect;
- cur_ace->n_sectors = n_sectors;
- cur_ace->mode = mode;
+ if (mode) {
+ cur_ace = kmalloc(sizeof(*cur_ace), GFP_KERNEL);
+ cur_ace->device = dev;
+ cur_ace->start_sect = start_sect;
+ cur_ace->n_sectors = n_sectors;
+ cur_ace->mode = mode;
- list_add_tail(&cur_ace->list, &p->physdisk_aces);
+ list_add_tail(&cur_ace->list, &p->physdisk_aces);
+ }
return 0;
}
int n_aces;
struct list_head *cur_ace_head;
struct physdisk_ace *cur_ace;
- int x;
+ int x = 0;
max_aces = buf->n_aces;
n_aces = 0;
list_for_each(cur_ace_head, &p->physdisk_aces) {
- if (x < buf->start_ind) {
- x++;
- continue;
+ x++;
+ if (x >= buf->start_ind) {
+ cur_ace = list_entry(cur_ace_head, struct physdisk_ace,
+ list);
+ buf->entries[n_aces].device = cur_ace->device;
+ buf->entries[n_aces].start_sect = cur_ace->start_sect;
+ buf->entries[n_aces].n_sectors = cur_ace->n_sectors;
+ buf->entries[n_aces].mode = cur_ace->mode;
+ n_aces++;
+ if (n_aces >= max_aces)
+ break;
}
- cur_ace = list_entry(cur_ace_head, struct physdisk_ace,
- list);
- buf->entries[n_aces].device = cur_ace->device;
- buf->entries[n_aces].start_sect = cur_ace->start_sect;
- buf->entries[n_aces].n_sectors = cur_ace->n_sectors;
- buf->entries[n_aces].mode = cur_ace->mode;
- n_aces++;
- if (n_aces >= max_aces)
- break;
}
buf->n_aces = n_aces;
- printk("Found a total of %x aces (max %x).\n", n_aces, max_aces);
}
int xen_physdisk_grant(xp_disk_t *xpd_in)
p = p->next_task;
} while (p != current && p->domain != xpd->domain);
if (p->domain != xpd->domain) {
- DPRINTK("Bad domain! No biscuit!\n");
+ DPRINTK("Bad domain!\n");
res = 1;
goto out;
}
return res;
}
-int xen_physdisk_revoke(xp_disk_t *xpd_in)
-{
- struct task_struct *p;
- xp_disk_t *xpd = map_domain_mem(virt_to_phys(xpd_in));
- int res;
-
- p = current;
-
- do {
- p = p->next_task;
- } while (p != current && p->domain != xpd->domain);
- if (p->domain != xpd->domain) {
- res = 1;
- goto out;
- }
- spin_lock(&p->physdev_lock);
- xen_physdisk_revoke_access(xpd->device,
- xpd->start_sect,
- xpd->n_sectors,
- p);
- spin_unlock(&p->physdev_lock);
- res = 0;
- out:
- unmap_domain_mem(xpd);
- return res;
-}
-
int xen_physdisk_probe(physdisk_probebuf_t *buf_in)
{
struct task_struct *p;
p = current;
do {
p = p->next_task;
- } while (p != current && p->domain != buf->domain);
+ } while (p != current && p->domain != buf->domain);
if (p->domain != buf->domain) {
res = 1;
goto out;
}
- printk("initially %x aces.\n", buf->n_aces);
spin_lock(&p->physdev_lock);
xen_physdisk_probe_access(buf, p);
spin_unlock(&p->physdev_lock);
- printk("%x aces.\n", buf->n_aces);
res = 0;
out:
unmap_domain_mem(buf);
#define XEN_BLOCK_SEG_DELETE 8 /* delete segment (vhd) */
#define XEN_BLOCK_PROBE_SEG 9 /* get vhd config from hypervisor */
#define XEN_BLOCK_PHYSDEV_GRANT 10 /* grant access to range of disk blocks */
-#define XEN_BLOCK_PHYSDEV_REVOKE 11 /* revoke access to range of disk blocks */
-#define XEN_BLOCK_PHYSDEV_PROBE 12 /* probe for a domain's physdev
+#define XEN_BLOCK_PHYSDEV_PROBE 11 /* probe for a domain's physdev
accesses */
/* NB. Ring size must be small enough for sizeof(blk_ring_t) <= PAGE_SIZE. */
xv_extent_t extents[XEN_MAX_DISK_COUNT]; /* arbitrary reuse of constant */
} xv_disk_t;
+#define PHYSDISK_MODE_R 1
+#define PHYSDISK_MODE_W 2
typedef struct xp_disk
{
- int mode;
+ int mode; /* 0 -> revoke existing access, otherwise bitmask of
+ PHYSDISK_MODE_? constants */
int domain;
unsigned short device;
unsigned long start_sect;
case XEN_BLOCK_SEG_CREATE:
case XEN_BLOCK_SEG_DELETE:
case XEN_BLOCK_PHYSDEV_GRANT:
- case XEN_BLOCK_PHYSDEV_REVOKE:
case XEN_BLOCK_PHYSDEV_PROBE:
case XEN_BLOCK_PROBE_BLK:
case XEN_BLOCK_PROBE_SEG:
case XEN_BLOCK_PROBE_SEG:
case XEN_BLOCK_PROBE_BLK:
case XEN_BLOCK_PHYSDEV_GRANT:
- case XEN_BLOCK_PHYSDEV_REVOKE:
case XEN_BLOCK_PHYSDEV_PROBE:
if ( bret->status )
printk(KERN_ALERT "Bad return from blkdev control request\n");
+/* We stuff the domain number into the proc_dir_entry data pointer. */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/proc_fs.h>
-static struct proc_dir_entry *phd;
-
extern int xenolinux_control_msg(int operration, char *buffer, int size);
-static ssize_t proc_read_phd(struct file * file, char * buff, size_t size, loff_t * off)
+static ssize_t proc_read_phd(struct file * file, char * buff, size_t size,
+ loff_t * off)
{
physdisk_probebuf_t *buf;
int res;
+ struct proc_dir_entry *pde;
if (size != sizeof(physdisk_probebuf_t))
return -EINVAL;
return -EFAULT;
}
- printk("max aces 1 %x\n", buf->n_aces);
+ pde = file->f_dentry->d_inode->u.generic_ip;
+ buf->domain = (int)pde->data;
+ /* The offset reported by lseek and friends doesn't have to be in
+ bytes, and it's marginally easier to say that it's in records, so
+ that's what we do. */
+ buf->start_ind = *off;
res = xenolinux_control_msg(XEN_BLOCK_PHYSDEV_PROBE, (void *)buf,
sizeof(physdisk_probebuf_t));
-
- printk("max aces %x\n", buf->n_aces);
+ *off += buf->n_aces;
if (res)
res = -EINVAL;
{
char *local;
int res;
+ xp_disk_t *xpd;
+ struct proc_dir_entry *pde;
if (count != sizeof(xp_disk_t))
return -EINVAL;
res = -EFAULT;
goto out;
}
- local[count] = 0;
+
+ xpd = (xp_disk_t *)local;
+
+ pde = file->f_dentry->d_inode->u.generic_ip;
+ xpd->domain = (int)pde->data;
res = xenolinux_control_msg(XEN_BLOCK_PHYSDEV_GRANT, local, count);
if (res == 0)
return res;
}
-static struct file_operations proc_phd_fops = {
+struct file_operations dom0_phd_fops = {
read : proc_read_phd,
write : proc_write_phd
};
-
-int __init xlphysdisk_proc_init(void)
-{
- phd = create_proc_entry("xeno/dom0/phd", 0644, NULL);
- if (!phd) {
- panic("Can\'t create phd proc entry!\n");
- }
- phd->data = NULL;
- phd->proc_fops = &proc_phd_fops;
- phd->owner = THIS_MODULE;
-
- return 0;
-}
#define DOM_MEM "mem"
#define DOM_VIF "vif"
#define DOM_USAGE "usage"
+#define DOM_PHD "phd"
#define MAP_DISCONT 1
+extern struct file_operations dom0_phd_fops;
+
struct proc_dir_entry *xeno_base;
static struct proc_dir_entry *dom0_cmd_intf;
static struct proc_dir_entry *proc_ft;
file->proc_fops = &dom_usage_ops;
file->data = (void *) dom;
}
+
+ file = create_proc_entry(DOM_PHD, 0600, dir);
+ if (file != NULL)
+ {
+ file->owner = THIS_MODULE;
+ file->nlink = 1;
+ file->proc_fops = &dom0_phd_fops;
+ file->data = (void *) dom;
+ }
}
static ssize_t dom_mem_write(struct file * file, const char * buff,
xlblk_init();
xlseg_init();
xlseg_proc_init();
- xlphysdisk_proc_init();
#endif
return 0;